package idgen

import (
	"gitee.com/tietang/terrace-go/v2/base/starter/iredis"
	"sync"
	"time"
)

type LocalIdGenerator struct {
	mu          sync.Mutex
	WorkerId    int64
	WorkerName  string
	WorkerIdKey string
	time        int64
	step        int64
	GenFunc     func(code int, millisecond int64, timestamp string, workId, incrId int64) interface{}
}

func NewLocalIdGenerator(workerId int64, workerName string) *LocalIdGenerator {
	return &LocalIdGenerator{
		time:       0,
		WorkerName: workerName,
		WorkerId:   workerId,
		step:       0,
	}
}

func (n *LocalIdGenerator) GetWorkerId() int64 {
	return n.WorkerId
}
func (n *LocalIdGenerator) GetWorkerName() string {
	return n.WorkerName
}
func (n *LocalIdGenerator) GetWorkerKey() string {
	return n.WorkerIdKey
}

func (n *LocalIdGenerator) Next(code int) (id string) {
	newId := n.next(code, n.GenFunc)
	return newId.(string)
}
func (n *LocalIdGenerator) NextSnowId() ID {
	newId := n.next(0, fnSnow)

	return newId.(ID)
}

func (n *LocalIdGenerator) next(code int, fn func(code int, millisecond int64, timestamp string, workId, incrId int64) interface{}) interface{} {

	n.mu.Lock()

	now := time.Now().UnixNano() / int64(time.Millisecond)

	if n.time == now {
		n.step++
		if n.step%WorkerMax == 0 {
			for now <= n.time {
				now = time.Now().UnixNano() / int64(time.Millisecond)
			}
		}
	} else {
		n.step = 0
	}

	n.time = now

	seconds := now / 1000
	nsec := now*int64(time.Millisecond) - seconds*int64(time.Second)
	w := time.Unix(seconds, nsec)
	timestamp := w.Format(iredis.ID_TIME_LAYOUT)

	id := fn(code, now, timestamp, n.WorkerId, n.step)

	n.mu.Unlock()
	return id
}
